package com.cx.base.autoDoc.utils;

import java.awt.Color;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.ObjectUtils.Null;
import org.springframework.stereotype.Controller;

import com.cx.base.apiModel.ApiModel;
import com.cx.base.autoDoc.annotations.AutoDocField;
import com.cx.base.autoDoc.annotations.AutoDocMethod;
import com.cx.base.autoDoc.annotations.AutoDocType;
import com.lowagie.text.BadElementException;
import com.lowagie.text.Cell;
import com.lowagie.text.Chapter;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Element;
import com.lowagie.text.Font;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.Section;
import com.lowagie.text.Table;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfWriter;

/**
 * 自动生成文档
 * cenxi 2015-11-11  
 * */
public class ServicePdfUtil {

	/**
	 * 3.新建一个字体,iText的方法 STSongStd-Light 是字体，在iTextAsian.jar 中以property为后缀
	 * UniGB-UCS2-H 是编码，在iTextAsian.jar 中以cmap为后缀 H 代表文字版式是 横版， 相应的 V 代表竖版
	 */
	// BaseFont bfChinese =
	// BaseFont.createFont("STSong-Light","UniGB-UCS2-H",BaseFont.NOT_EMBEDDED);
	private static BaseFont bfChinese = null;

	private static Font headfont = null; // 设置字体大小
	private static Font bigFont = null; // 设置字体大小
	private static Font middleFont = null; // 设置字体大小
	private static Font smallFont = null; // 设置字体大小
	private static Font minimumFont = null; // 设置字体大小

	private static float leading = 20f;// 行间距

	static {
		try {
			bfChinese = BaseFont.createFont("C:/WINDOWS/Fonts/SIMSUN.TTC,1",BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		headfont = new Font(bfChinese, 16, Font.BOLD); // 设置字体大小
		bigFont = new Font(bfChinese, 14, Font.BOLD); // 设置字体大小
		middleFont = new Font(bfChinese, 12, Font.BOLD); // 设置字体大小
		smallFont = new Font(bfChinese, 10, Font.NORMAL); // 设置字体大小
		minimumFont = new Font(bfChinese, 9, Font.NORMAL); // 设置字体大小
	}
	
	/**
	 * 生成pdf文件
	 * */
	public static void createPdf(String path,String FileName,List<Class> clazzes) {
		
		path = path+"/"+FileName+".PDF";
		
		FileUtil.delFile(path);
		
		try {
			/**
			 * 1.建立com.lowagie.text.Document对象的实例。
			 * Document(Rectangle pageSize,int marginLeft,int marginRight,int marginTop,int marginBottom); 
			 * */
			Document document = new Document(PageSize.A4,5,5,2,2); 
			/**
			 * 2.建立一个书写器(Writer)与document对象关联，通过书写器(Writer)可以将文档写入到磁盘中。
			 * */
			PdfWriter.getInstance(document, new FileOutputStream(path));
			
			
			
			//设置内容
			document.addTitle("标题");
			document.addSubject("subject");
			document.addKeywords("关键字");
			document.addAuthor("生产者");
			document.addCreator("创建者");
			document.addProducer();
			document.addCreationDate();
			
			if(clazzes != null && clazzes.size() > 0){
				// 打开文档。
				document.open();
				int i = 0;
				for(Class clazz : clazzes){
					i++;
					//获取类标题
					AutoDocType autoDocType = (AutoDocType) clazz.getAnnotation(AutoDocType.class);
					Chapter classChapter = new Chapter(new Paragraph(autoDocType.value(), bigFont), i);
					
					String classUrl = "";
					Class[] interfacesClazzes = clazz.getInterfaces();
					if(interfacesClazzes.length > 0){
						classUrl = interfacesClazzes[0].getName();
					}
					
					Method[] methods = clazz.getMethods();
					
					if(methods != null && methods.length > 0){
						int j=0;
						for(Method method : methods){
							AutoDocMethod autoDocMethod = method.getAnnotation(AutoDocMethod.class);
							if(autoDocMethod != null){
								j++;
								//添加方法标题
								Paragraph sessionTitle = new Paragraph(leading*2, autoDocMethod.name(), middleFont);
								Section session = classChapter.addSection(sessionTitle);
								
								//请求地址
								Paragraph url = new Paragraph(leading, StringUtil.getStrAddBeforeSpace("接口地址："+classUrl), smallFont);
								session.add(url);
								
								//方法名
								Paragraph funName = new Paragraph(leading, StringUtil.getStrAddBeforeSpace("方法名称："+method.getName()), smallFont);
								session.add(funName);
								
								//描述
								Paragraph desc = new Paragraph(leading, StringUtil.getStrAddBeforeSpace("说明："+autoDocMethod.desc()), smallFont);
								session.add(desc);
								
								/****start 传入参****/
								session.add(new Paragraph(leading, StringUtil.getStrAddBeforeSpace("传参："), smallFont));
								
								Table inTable = getTable();
								
								//获取方法传参注解
								Class<?>[] parameterTypes = method.getParameterTypes();
								Annotation[][] parameterAnnotations = method.getParameterAnnotations();
								
								//基本类型方法传参名
								String[] parameterNames = ParameterNameUtils.getMethodParameterNamesByAsm4(clazz, method);
								
								if(parameterTypes != null && parameterTypes.length > 0){
									int paraInt = 0;
									for(Class parameterType : parameterTypes){
										Boolean flag = true;
										Annotation[] annotationTemps = parameterAnnotations[paraInt];
										
										//基本类型传参
										if(annotationTemps != null && annotationTemps.length > 0){
											for(Annotation annotationTemp : annotationTemps){
												if(annotationTemp.annotationType().equals(AutoDocField.class)){
													AutoDocField autoDocField = (AutoDocField)annotationTemp;
													//基本类型传参（AutoDocField注解不这空时，为基本传参类型）
													if(autoDocField != null){
														inTable.addCell(getTableCell(parameterNames[paraInt]));
														String fieldType = parameterType.getName();
														fieldType = fieldType.substring(fieldType.lastIndexOf(".")+1);
														inTable.addCell(getTableCell(fieldType));
														
														inTable.addCell(getTableCell(autoDocField.value()));
														flag = false;
													}
												}
											}
										}
										//非基本类型时读取对象里的属性
										if(flag){
											Field[] fields = parameterType.getDeclaredFields();
											if(fields != null && fields.length > 0){
												for(Field field : fields){
													AutoDocField autoDocField = field.getAnnotation(AutoDocField.class);
													if(autoDocField != null){
														inTable.addCell(getTableCell(field.getName()));
														
														//字段类型
														String fieldType = field.getType().getName();
														fieldType = fieldType.substring(fieldType.lastIndexOf(".")+1);
														inTable.addCell(getTableCell(fieldType));
														
														inTable.addCell(getTableCell(autoDocField.value()));
													}
												}
											}
										}
										paraInt++;
									}
								}
								session.add(inTable);
								/****end 传入参****/
								
								/****start 返回参数****/
								Field[] resFields = method.getReturnType().getDeclaredFields();
								Class resClazz = autoDocMethod.resClazz();

								session.add(new Paragraph(leading, StringUtil.getStrAddBeforeSpace("返回参："), smallFont));
								Table outTable = getTable();
								if(resFields != null && resFields.length > 0){
									for(Field field : resFields){
										AutoDocField autoDocField = field.getAnnotation(AutoDocField.class);
										if(autoDocField != null){
											outTable.addCell(getTableCell(field.getName()));

											//字段类型
											String fieldType = field.getType().toString();
											fieldType = fieldType.substring(fieldType.lastIndexOf(".")+1);
											outTable.addCell(getTableCell(fieldType));
											
											outTable.addCell(getTableCell(autoDocField.value()));
										}
									}
								}
								
								if(resClazz != null){
									
									List<String[]> fieldList = getFieldAnnotations(resClazz,new ArrayList<String[]>());
									if(fieldList != null && fieldList.size() > 0){
										for(String[] ss : fieldList){
											//字段名
											outTable.addCell(getTableCell(ss[0]));
											//字段类型
											outTable.addCell(getTableCell(ss[1]));
											//中文注解
											outTable.addCell(getTableCell(ss[2]));
										}
									}
								}
								session.add(outTable);
								/****end 返回参数****/
								
							}
						}
					}
					
					document.add(classChapter);
				}
				
				
			}
			// 关闭文档。
			document.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		

	}
	
	/**
	 * 获取一个表格
	 * */
	public static  Table getTable(){
		
		try {
			Table table = new Table(3);
			table.setBorderWidth(0);
			table.setBorderColor(new Color(255, 250, 250));
			table.setPadding(0);
			table.setSpacing(0);
			float[] fs = {0.3f,0.1f,0.6f};
			table.setWidths(fs); 
			table.setAlignment(Element.ALIGN_MIDDLE);//垂直居中

			table.addCell(getTableCell("名称"));
			table.addCell(getTableCell("类型"));
			table.addCell(getTableCell("描述"));
			return table;
		} catch (Exception e) {
			// TODO: handle exception
		}
		return null;
	}
	
	/**
	 * 获取表格单元
	 * */
	public static Cell getTableCell(String str) {
		str = str+"\n";
		try {
			Paragraph para = new Paragraph(leading, str, minimumFont);
			//设置该段落为居中显示
	        para.setAlignment(Paragraph.ALIGN_MIDDLE);
	        para.setIndentationLeft(5f);
	        
			Cell cell = new Cell(para);
			cell.setBottom(0.1f);
			cell.setTop(0.1f);
			cell.setHorizontalAlignment(cell.ALIGN_LEFT);
			cell.setVerticalAlignment(cell.ALIGN_JUSTIFIED_ALL);

			return cell;
		} catch (BadElementException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	
	/**
	 * 获取表格单元(字体间距小的)
	 * */
	public static Cell getTableCell2(String str) {
		str = str+"\n";
		try {
			Paragraph para = new Paragraph(leading, str, minimumFont);
			//设置该段落为居中显示
	        para.setAlignment(Paragraph.ALIGN_MIDDLE);
	        para.setIndentationLeft(5f);
	        para.setLeading(7f);
	        para.setSpacingAfter(10f);
			
			Cell cell = new Cell(para);
			cell.setBottom(0.1f);
			cell.setTop(0.1f);
			cell.setVerticalAlignment(Cell.ALIGN_MIDDLE);

			return cell;
		} catch (BadElementException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	
	
	/**
	 * 获取对象属性注解
	 * */
	public static List<String[]> getFieldAnnotations(Class clazz,List<String[]> list){
		Field[] fields = clazz.getDeclaredFields();
		if(fields != null && fields.length > 0){
			for(Field field : fields){
				AutoDocField autoDocField = field.getAnnotation(AutoDocField.class);
				if(autoDocField != null){
					if(autoDocField.clazz() != Null.class){
						Class fieldClazz = autoDocField.clazz();
						list = getFieldAnnotations(fieldClazz,list);
					}else{
						String[] ss = new String[3];
						//字段名
						ss[0] = field.getName();
						
						//字段类型
						String fieldType = field.getType().toString();
						fieldType = fieldType.substring(fieldType.lastIndexOf(".")+1);
						ss[1] = fieldType;
						
						//中文名
						ss[2] = autoDocField.value();
						list.add(ss);
					}
					
				}
			}
		}
		return list;
	}
	

}
